class PhotoUpload
  attr_accessor :photo
  
  IMAGE_MAX_WIDTH = 640
  IMAGE_MAX_HEIGHT = 480
  THUMBNAIL_MAX_WIDTH = 80
  THUMBNAIL_MAX_HEIGHT = 60

  def initialize(photo_set, data)
    @photo_set = photo_set
      
    @photo = Photo.new({
      :published => false })
    @photo.photo_set = @photo_set
    @photo.save
    
    FileUtils.makedirs(with_root(@photo.photo_set_path))
    
    @file_data = data
    write_temp if data.kind_of? StringIO
    
    if save
      @photo.published = true
      @photo.save
    end
  end

  def write_temp
    tmp = Tempfile.new("upload")
    @file_data.rewind
    tmp.binmode
    tmp.write @file_data.read
    tmp.rewind
    @file_data = tmp
  end
  
  def save
    # Save the photo with 
    # 1. thumbnail with max 80px width or 70px height with ratio
    # 2. resized with max 800px width or 700px height with ratio
    begin
      @save_error = !ImageScience.with_image(@file_data.path) do |image|
        r = image.width / image.height.to_f
        
        # Thumbnail
        w, h = scaled(THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, r)
        image.resize(w, h) do |img|
            img.save(with_root(@photo.path(true)))
        end

        # Resized
        if image.width > IMAGE_MAX_WIDTH || image.height > IMAGE_MAX_HEIGHT
          w, h = scaled(IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, r)
          image.resize(w, h) do |img|
            img.save(with_root(@photo.path))
          end
        else
          image.resize(image.width, image.height) do |img|
            img.save(with_root(@photo.path))
          end
        end
      end
    rescue TypeError
      @save_error = true
    end
    
    !@save_error
  end
  
  private
    def scaled(w, h, r)
      (r <= 1 ? 
        [ r * h, h ] : 
        [ w, 1.0/r * w ]).map do |v|
          v.round <= 0 ? 1 : v.round
      end
    end
    
    def with_root(path)
      "#{RAILS_ROOT}/public#{path}"
    end
  
end
